﻿
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Wise.Util;

namespace Wise.Entities
{
    public interface IConfig
    {
        string GetConfigFileFullName();
        CustomeSerialize GetObjectToStream();
        CustomeDeserialize GetStreamToObject();
        TItem Read<TItem>() where TItem : class, IConfig, new();
        void SetObjectToStream(CustomeSerialize handler);
        void SetStreamToObject(CustomeDeserialize hanlder);
        void SubmitChanges();
        void Write(string fileFullName);
    }
    //
    // 摘要:
    //     反序列化委托
    //
    // 参数:
    //   fs:
    public delegate object CustomeDeserialize(FileStream fs);
    //
    // 摘要:
    //     序列化委托
    //
    // 参数:
    //   obj:
    //
    //   fs:
    public delegate void CustomeSerialize(object obj, FileStream fs);


    public class JsonConfig : IConfig
    {

        public JsonConfig()
        {
            MyDeserialize = Getter;
            MySerialize = Setter;
        }

        public JsonConfig(string fileFullName) : this()
        {
            FileFullName = fileFullName;
        }

        string FileFullName { get; set; }

        public string GetConfigFileFullName()
        {
            return FileFullName;
        }

        public CustomeSerialize GetObjectToStream()
        {
            return MySerialize;
        }

        public CustomeDeserialize GetStreamToObject()
        {
            return MyDeserialize;
        }

        public TItem Read<TItem>() where TItem : class, IConfig, new()
        {
            if (!File.Exists(FileFullName))
            {
                return new TItem();
            }

            using (FileStream fs = new FileStream(FileFullName, FileMode.Open))
            {
                Object obj = MyDeserialize.Invoke(fs);
                return obj as TItem;
            }
        }

        public void SetObjectToStream(CustomeSerialize handler)
        {
            MySerialize = handler;
        }

        public void SetStreamToObject(CustomeDeserialize handler)
        {
            MyDeserialize = handler;
        }
        void Setter(Object obj, FileStream fs)
        {
            string json = JsonHelper.ToJson_expand(obj);
            byte[] buffer = Encoding.UTF8.GetBytes(json);
            fs.Write(buffer, 0, buffer.Length);
        }
        Object Getter(FileStream fs)
        {
            byte[] buffer = new byte[fs.Length];
            fs.Read(buffer, 0, buffer.Length);
            string json = Encoding.UTF8.GetString(buffer);
            string json1 = _Trimer_Start.Replace(json, string.Empty);
            string json2 = _Trimer_End.Replace(json1, string.Empty);
            //从json文件中读取出来后默认有个空白字符
            return JsonHelper.ToObject(json2, this.GetType());
        }

        Regex _Trimer_Start = new Regex("^[^\\{|\\[]+", RegexOptions.Compiled | RegexOptions.IgnoreCase);
        Regex _Trimer_End = new Regex("[^\\}|\\]]+$", RegexOptions.Compiled | RegexOptions.IgnoreCase);

        CustomeDeserialize MyDeserialize = null;
        CustomeSerialize MySerialize = null;


        /// <summary>
        /// 提交更改，等同于Write(cfg.GetConfigFileFullName())
        /// </summary>
        public void SubmitChanges()
        {
            this.Write(this.GetConfigFileFullName());
        }

        /// <summary>
        /// 写入配置文件
        /// </summary>
        /// <param name="obj"></param>
        public void Write(string fileFullName)
        {
            if (string.IsNullOrEmpty(fileFullName))
            {
                throw new ArgumentNullException("FileName");
            }
            if (File.Exists(fileFullName))
            {
                File.Delete(fileFullName);
            }
            using (FileStream fs = File.OpenWrite(fileFullName))
            {
                MySerialize.Invoke(this, fs);
            }
        }

    }

    public class JsonConfig<TConfig> : JsonConfig
        where TConfig : JsonConfig, new()
    {
        public JsonConfig()
        {

        }
        public JsonConfig(string fileFullName) : base(fileFullName)
        {
            TConfig cfg = this.Read();
            //ObjectHelper.WiseCloneByProperty(cfg,this);
            cfg.CopyTo(this);
        }

        public TConfig Read()
        {
            return base.Read<TConfig>();
        }

        public static TConfig Current { get; set; }
    }
}
